﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Common;

namespace DIOCheckSum
{
    public partial class Form1 : Form
    {
        long dwPolynomial = 0xEDB88320;
        long[] m_dwCrc32Table;
        bool m_get = false;

        public Form1()
        {
            InitializeComponent();

            
        }

        private void label2_Click(object sender, EventArgs e)
        {

        }

        private void tb_cs_TextChanged(object sender, EventArgs e)
        {

        }

        private void btn_get_Click(object sender, EventArgs e)
        {
            if (ofd_file.ShowDialog() != DialogResult.OK)
            {
                return;
            }

            tb_file.Text = ofd_file.FileName;
            label3.Text = "Calced Size: 0MB";
            //label3.Update();
            tb_cs.Text = "0x00000000";
        }

        private void btn_calc_Click(object sender, EventArgs e)
        {
            string cstype = cb_cstype.Text;
            string filedir = tb_file.Text;
            FileStream fs = new FileStream(filedir, FileMode.Open);
            BinaryReader brr = new BinaryReader(fs);
            Int64 checksum_value = 0;
            Int64 cnt = (Int64)fs.Length;
            Int64 i;
            Int64 cnt_loop = 0;
            //if (cnt > 0x40000000)
            //{
            //    cnt_loop = 0x100000;
            //}
            //else if (cnt > 0x100000)
            //{ 
            //    cnt_loop = 
            //}

            switch (cstype)
            {
                case "8 bit checksum":
                    byte tempbyte = 0;
                    for (i = 0; i < cnt; i++)
                    {
                        tempbyte = brr.ReadByte();
                        checksum_value += tempbyte;
                        cnt_loop++;
                        if (cnt_loop % 0x100000 == 0)
                        {
                            label3.Text = "Calced Size: " + (cnt_loop / 0x100000).ToString() + "MB";
                            label3.Update();
                            //tb_cs.Text = "CalcSize: " + (cnt_loop / 0x100000).ToString() + "MB";
                        }
                        //if (i == 0)
                        //{
                        //    MessageBox.Show(checksum_value.ToString("X"));
                        //}
                        if (checksum_value > 0xFFFFFFFF)
                        {
                            // cut all above
                            //MessageBox.Show(checksum_value.ToString("X"));
                            checksum_value &= 0xFFFFFFFF;
                            //MessageBox.Show(checksum_value.ToString("X"));
                        }
                    }
                    MessageBox.Show("8 bit checksum calculation done.");
                    break;
                case "16 bit checksum":
                    int tempint = 0;
                    for (i = 0; i < cnt / 2; i++)
                    {
                        tempint = (int)brr.ReadByte();
                        tempint &= 0x00FF;
                        checksum_value += tempint;
                        cnt_loop++;
                        tempint = (int)brr.ReadByte(); ;
                        tempint = (tempint * 256) & 0xFF00;
                        checksum_value += tempint;
                        cnt_loop++;
                        if (cnt_loop % 0x100000 == 0)
                        {
                            label3.Text = "Calced Size: " + (cnt_loop / 0x100000).ToString() + "MB";
                            label3.Update();
                            //tb_cs.Text = "CalcSize: " + (cnt_loop / 0x100000).ToString() + "MB";
                        }
                        //if (i == 0)
                        //{
                        //    MessageBox.Show(checksum_value.ToString("X"));
                        //}
                        if (checksum_value > 0xFFFFFFFF)
                        {
                            // cut all above
                            //MessageBox.Show(checksum_value.ToString("X"));
                            checksum_value &= 0xFFFFFFFF;
                            //MessageBox.Show(checksum_value.ToString("X"));
                        }
                    }
                    MessageBox.Show("16 bit checksum calculation done.");
                    break;
                case "32 bit checksum":
                    UInt32 tempint32 = 0;
                    for (i = 0; i < cnt / 4; i++)
                    {
                        tempint32 = brr.ReadUInt32();
                        checksum_value += tempint32;
                        cnt_loop += 4;
                        if (cnt_loop % 0x100000 == 0)
                        {
                            label3.Text = "Calced Size: " + (cnt_loop / 0x100000).ToString() + "MB";
                            label3.Update();
                            //tb_cs.Text = "CalcSize: " + (cnt_loop / 0x100000).ToString() + "MB";
                        }
                        //if (i == 0)
                        //{
                        //    MessageBox.Show(checksum_value.ToString("X"));
                        //}
                        if (checksum_value > 0xFFFFFFFF)
                        {
                            // cut all above
                            //MessageBox.Show(checksum_value.ToString("X"));
                            checksum_value &= 0xFFFFFFFF;
                            //MessageBox.Show(checksum_value.ToString("X"));
                        }
                    }
                    MessageBox.Show("32 bit checksum calculation done.");
                    break;
                default:
                    MessageBox.Show("no other type of checksum!");
                    break;
            }
            
            if (0x00000000 != checksum_value)
            {
                tb_cs.Text = "0x" + checksum_value.ToString("X");
            }
            else
            {
                tb_cs.Text = "0x00000000";
            }

            fs.Close();
            brr.Close();
        }

        private void cb_cstype_SelectedIndexChanged(object sender, EventArgs e)
        {
            tb_file.Text = ofd_file.FileName;
            label3.Text = "Calced Size: 0MB";
            //label3.Update();
            tb_cs.Text = "0x00000000";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // 
            string cstype = cb_cstype.Text;
            string filedir = tb_file.Text;
            FileStream fs = new FileStream(filedir, FileMode.Open);
            BinaryReader brr = new BinaryReader(fs);
            Int64 crcsum_value = 0xffffffff;
            Int64 cnt = (Int64)fs.Length;
            Int64 i;
            Int64 cnt_loop = 0;
            byte tempbyte = 0;
            for (i = 0; i < cnt; i++)
            {
                tempbyte = brr.ReadByte();
                // crcsum_value += tempbyte;
                CalcCrc32(tempbyte, ref crcsum_value);
                cnt_loop++;
                if (cnt_loop % 0x100000 == 0)
                {
                    label3.Text = "Get Crc Value: " + (cnt_loop / 0x100000).ToString() + "MB";
                    label3.Update();
                    //tb_cs.Text = "CalcSize: " + (cnt_loop / 0x100000).ToString() + "MB";
                }
                //if (i == 0)
                //{
                //    MessageBox.Show(checksum_value.ToString("X"));
                //}
                //if (crcsum_value > 0xFFFFFFFF)
                //{
                //    // cut all above
                //    //MessageBox.Show(checksum_value.ToString("X"));
                //    crcsum_value &= 0xFFFFFFFF;
                //    //MessageBox.Show(checksum_value.ToString("X"));
                //}
            }
            crcsum_value = crcsum_value ^ 0xFFFFFFFF;
            if (0x00000000 != crcsum_value)
            {
                textBox1.Text = "0x" + crcsum_value.ToString("X");
            }
            else
            {
                textBox1.Text = "0x00000000";
            }

            fs.Close();
            brr.Close();

            MessageBox.Show("try crc32 calculation");
        }

        private void CalcCrc32(byte my_byte, ref long crc_32)
        {
            GetCRC32Table();
            crc_32 = ((crc_32 >> 8) & 0x00FFFFFF) ^ m_dwCrc32Table[(my_byte ^ crc_32) & 0x000000FF];
        }

        private void Compute8(byte[] buff_p, long num_bytes, ref long crc_32)
        {
            for (int i = 0; i < num_bytes; i++)
            {
                CalcCrc32(buff_p[i], ref crc_32);
            }
        }

        private void GetCRC32Table()
        {
            if (m_get == true)
                return;
            m_dwCrc32Table = new long[256];
            for (long i = 0; i < 256; i++)
            {
                long dwCrc = i;
                for (int j = 8; j > 0; j--)
                {
                    if ((dwCrc & 1) != 0)
                    {
                        dwCrc = (dwCrc >> 1) ^ dwPolynomial;
                    }
                    else
                    {
                        dwCrc >>= 1;
                    }
                }
                m_dwCrc32Table[i] = dwCrc;

            }
            m_get = true;
            //MessageBox.Show(m_dwCrc32Table[1].ToString("X"));
        }
    }
}
